using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Diagnostics;

namespace Assignment3
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        BasicEffect effect;                     // effect for lighting and transformation matrices
        bool IsDay = true;
        bool IsFoggy = false;
        public int Zoom = 0;


        Maze maze;

        KeyboardState currentKeyboardState;     // maintain keyboard state to avoid key repetition when needed
        KeyboardState lastKeyboardState;
        GamePadState currentGamePadState;       // Same as above but for gamepad
        GamePadState lastGamePadState;

        Camera camera;

        SpriteFont font;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
           
            Content.RootDirectory = "Content";

#if XBOX
            graphics.PreferredBackBufferHeight = (int)720;
            graphics.PreferredBackBufferWidth = (int)1280;
#endif

        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // Setup Camera / Matrices (World/View/Projection)
            Vector3 startingPosition = new Vector3(-2.5f, 0, -4f);

            // use a unit vector
            Vector3 startingDirection = new Vector3(0, 0, 1);



            Matrix world = Matrix.Identity;

            //camera = new Camera(graphics);
            camera = new Camera(graphics, startingPosition, startingDirection);

            camera.avatarYaw = -1.5f;
            effect = new BasicEffect(graphics.GraphicsDevice);
            effect.EnableDefaultLighting();

            effect.World = world;

            effect.FogColor = Color.Gray.ToVector3(); // For best results, ake this color whatever your background is.
            effect.FogStart = 9.75f;
            effect.FogEnd = 10.25f;

           

     

            //myWall2.RotateShape(new Vector3(90.0f, 0.0f, 0.0f));    

            maze = new Maze(effect);

            GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp;

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            font = Content.Load<SpriteFont>("font");

            maze.LoadTextures(Content);
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            lastGamePadState = currentGamePadState;
            lastKeyboardState = currentKeyboardState;
            currentKeyboardState = Keyboard.GetState();
            currentGamePadState = GamePad.GetState(PlayerIndex.One);
            HandleInput();
            camera.HandleInput(maze);
            camera.UpdateCamera();

            effect.View = camera.view;
            effect.Projection = camera.proj;
            effect.LightingEnabled = true;

            CheckVisualEffects();



            base.Update(gameTime);
        }

        private void CheckVisualEffects()
        {

            if (IsDay)
            {
                effect.AmbientLightColor = new Vector3(.9f, .9f, .9f);

            }
            else
            {
                effect.AmbientLightColor = new Vector3(.1f, .1f, .1f);
            }


                effect.FogEnabled = IsFoggy;

            
        }

        void HandleInput()
        {


            if(IsPressed(Keys.T,Buttons.RightShoulder)){
               IsDay = !IsDay;
            }
            if(IsPressed(Keys.F , Buttons.LeftShoulder)){
            
                IsFoggy = !IsFoggy;
            }
            

            // Check for exit.
            if (IsPressed(Keys.Escape, Buttons.Back))
            {
                Exit();
            }

            if (IsPressed(Keys.Home, Buttons.Start))
            {
                camera.ResetCamera();
            }
        }

        /// <summary>
        /// Checks whether the specified key or button has been pressed.
        /// </summary>
        bool IsPressed(Keys key, Buttons button)
        {
            Debug.WriteLine("" + currentKeyboardState.IsKeyDown(key) + "  " + lastKeyboardState.IsKeyUp(key) );
            return (currentKeyboardState.IsKeyDown(key) &&
                    lastKeyboardState.IsKeyUp(key)) ||
                   (currentGamePadState.IsButtonDown(button) &&
                    lastGamePadState.IsButtonUp(button));
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            maze.Draw(GraphicsDevice);

            base.Draw(gameTime);
        }
    }
}
